//! 用户操作相关的路由
use std::sync::Arc;

use ane_system::dao::{ChangePasswordDo, UpdateUserDo};
use axum::{
    response::IntoResponse,
    routing::{get, put},
    Extension, Router,
};
use loginmanager::AuthUser;

use crate::{
    error::AppResult,
    extract::{Json, ValJson},
    security::LoginUser,
    state::AppState,
};

/// 登陆用户操作相关的路由
/// - {prefix}/info 获取及更新用户信息
/// - {prefix}/dept 获取用户可访问单位
/// - {prefix}/resource 获取用户可访问的资源
/// - {prefix}/change_password 修改密码
pub fn get_route(prefix: &str) -> Router<AppState> {
    let f = move |p: &str| -> String { format!("{}{p}", prefix) };
    Router::new()
        .route(&f("/info"), get(account_info).put(account_update))
        .route(&f("/change_password"), put(account_update_pasword))
        .route(&f("/resource"), get(account_resource))
        .route(&f("/dept"), get(account_dept))
}

pub async fn account_info(
    Extension(state): Extension<AppState>,
    AuthUser(user): AuthUser<LoginUser>,
) -> AppResult<impl IntoResponse> {
    ane_system::dao::User::get_detail_by_id(state.db(), user.id, None, None, false)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn account_update(
    Extension(state): Extension<AppState>,
    AuthUser(user): AuthUser<LoginUser>,
    ValJson(mut data): ValJson<UpdateUserDo>,
) -> AppResult<impl IntoResponse> {
    data.dept_id = None;
    data.password = None;
    data.status = None;
    ane_system::dao::User::update(state.db(), user.id, data)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn account_update_pasword(
    Extension(state): Extension<AppState>,
    AuthUser(user): AuthUser<LoginUser>,
    ValJson(data): ValJson<ChangePasswordDo>,
) -> AppResult<impl IntoResponse> {
    ane_system::dao::User::change_password2(state.db(), user.id, data)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn account_resource(
    Extension(state): Extension<AppState>,
    AuthUser(user): AuthUser<LoginUser>,
) -> AppResult<impl IntoResponse> {
    ane_system::dao::User::get_resource(state.db(), user.id)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn account_dept(
    Extension(state): Extension<AppState>,
    AuthUser(user): AuthUser<LoginUser>,
) -> AppResult<impl IntoResponse> {
    let data = match user.data_scope() {
        1 | 3 | 4 => {
            let d_id = if user.data_scope() == 1 { 1 } else { user.d_id };
            ane_system::dao::Dept::get_tree(state.db(), d_id, Some(true))
                .await?
                .map(|mut f| {
                    if user.data_scope() == 4 {
                        f.children = None;
                        f
                    } else {
                        f
                    }
                })
        }
        _ => None,
    };
    Ok(Json(data))
}
